#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <string>
using namespace std;

void* start(void* args)
{
    const char* name = (const char *)args;
    while(true)
    {
        printf("我是新线程 %s ，我的地址：0x%lx\n",name,pthread_self());
        sleep(1);
    }
    return nullptr;
}

int main()
{
    pthread_t tid1;
    pthread_create(&tid1,nullptr,start,(void*)"thread-1");
    printf("我是主线程，我的地址：0x%lx\n",pthread_self());
    void* ret = nullptr;
    pthread_join(tid1,&ret);
    return 0;
}

// class ThreadData
// {
// public:
//     ThreadData(){}
//     void Init(const string &name, int a,int b)
//     {
//         _name = name;
//         _a = a;
//         _b = b;
//     }
//     int add()
//     {
//         _result = _a + _b;
//     }
//     string Getname()
//     {return _name;}
//     void SetId(pthread_t tid){_tid = tid;}
//     pthread_t Id(){return _tid;}
//     int Result(){return _result;}
//     ~ThreadData()
//     {}
// private:
//     string _name;
//     int _a;
//     int _b;
//     int _result;
//     pthread_t _tid;
// };

// // 5. 全局变量在线程内部是共享的
// int gval = 100;

// string toHex(pthread_t tid)
// {
//     // 4. 进程内的函数，线程共享
//     char buffer[64];
//     snprintf(buffer,sizeof(buffer), "0x%lx" ,tid);
//     return buffer;
// }


// void* routinue2(void* args)
// {
//     ThreadData* name = (ThreadData*)args;
//     while (true)
//     {
//         // 3. 在不加保护的情况下，显示器文件就是共享资源
//         cout <<"I am new thread...." << name->Getname() <<",my tid is :" << toHex(pthread_self())  <<",全局变量(检测)" << gval <<endl;
//         sleep(1);
//         break;
//         // 6. 线程一旦出现异常，可能导致其他线程全部崩溃
//         // 6.1 信号
//         // int* p = nullptr;
//         // *p = 100;
//     }
//     // 8.返回值问题：返回参数，可以是变量，数字，对象
//     // 8.1：理论上，堆空间也是共享的！谁拿着堆空间的入口地址，谁就能访问堆区
//     return (void*)6; // 线程退出方式1：线程入口函数return，表示线程退出
// }

// // 被重入
// // void* routinue1(void* args)
// // {
// //     // string name = static_cast<const char*>(args);
// //     string name = static_cast<const char*>(args)
// //     while (true)
// //     {
// //         // 3. 在不加保护的情况下，显示器文件就是共享资源
// //         gval++;
// //         cout <<"I am new thread...." << name <<",my tid is :" << toHex(pthread_self()) <<",全局变量(修改)" << gval <<endl;
// //         sleep(1);
// //     }
// //     return 0;
// // }

// // 创建多个线程
// #define NUM 10

// int main()
// {
//     ThreadData td[NUM];
//     // 准备我们要加工处理的数据
//     for(int i = 0; i < NUM; i++)
//     {
//         char id[64];
//         snprintf(id,sizeof(id),"thread-%d",i);
//         td[i].Init(id,i*10,i*20);
//     }

//     // 创建多线程
//     for(int i = 0; i < NUM; i++)
//     {
//         pthread_t id;
//         pthread_create(&id,nullptr,routinue2,&td[i]);
//     }

//     // 等待多个线程
//     for(int i = 0; i < NUM; i++)
//     {
//         pthread_join(td[i].Id(),nullptr);
//     }

//     // // 8. 传参问题
//     // pthread_t tid1;
//     // ThreadData *td = new ThreadData("thread-1",10,20);
//     // pthread_create(&tid1,nullptr,routinue2,td);

//     // // 7. 线程创建之后，也是要被等待和回收的！
//     // // 7.1 理由：a. 类似僵尸进程的问题 b. 为了知道新线程的执行结果
//     // void *ret = nullptr;
//     // int n = pthread_join(tid1,&ret);
//     // if(n != 0)
//     // {
//     //     cerr << "join error: " << n << ", " << strerror(n) << endl;
//     //     return 1;
//     // }
//     // cout << "join success! " << (long)ret <<endl;

//     // pthread_t tid2;
//     // pthread_create(&tid2,nullptr,routinue2,(void*)"thread-2");

//     // printf("new thread 1 id : 0x%lx \n",tid1);
//     // printf("new thread 2 id : 0x%lx \n",tid2);


//     // while (true)
//     // {
//     //     cout <<"I am main thread...." << endl;
//     //     sleep(1);
//     // }
    
// }


// int main()
// {
//     // 1. 新线程和main线程谁先运行，不确定
//     // 2. 线程创建出来，要对进程的时间片进行瓜分
//     pthread_t tid;
//     pthread_create(&tid,nullptr,routinue,(void*)"thread-1");

//     printf("new thread id : 0x%lx \n",tid);
//     // cout << "new thread id: " << tid << endl;
//     while (true)
//     {
//         cout <<"I am main thread...." << endl;
//         sleep(1);
//     }
    
// }